import styles from "@styles/news.module.less";
import NewsItem from "@pages/home/widgets/news/NewsItem";
import { useOutletContext, useParams } from "react-router-dom";
import { useLazyRequestNewsQuery } from "@service/newsEndpoints";
import { useTypedDispatch, useTypedSelector } from "@store/index";
import { saveDistance, saveNews, selectChannelNews } from "@slice/news";
import Infinite from "@shared/infinite";
import { useEffect } from "react";
import { OutletContextProps } from "@shared/mainLayout";

export default function News() {
  // 1. 从路由参数中获取频道 id
  const cid = useParams().cid!;
  // 2. 得到用于获取新闻列表的钩子函数
  const [requestNews] = useLazyRequestNewsQuery();
  // 3. 从状态切片中获取频道 id 对应的新闻列表
  const channelNews = useTypedSelector(selectChannelNews(cid));
  // 获取 dispatch 方法
  const dispatch = useTypedDispatch();
  const { getScrollTop, setContainerScrollTop } =
    useOutletContext<OutletContextProps>();
  // 获取当前频道对应的滚动位置
  const distance = useTypedSelector((state) => state.news[cid]?.distance);

  // 4. 编写 loadMore 方法, 传递给 infinite 组件
  const loadMore = () => {
    // 发送请求 获取新闻列表
    // 5. 根据本地是否存在新闻列表判断当前是否是获取第一页的数据
    return requestNews({
      channel_id: cid,
      timestamp:
        typeof channelNews === "undefined"
          ? Date.now() + ""
          : channelNews.pre_timestamp,
    })
      .unwrap()
      .then((response) => {
        // 6. 将服务端返回的新闻列表保存到本地
        const { results, pre_timestamp } = response.data;
        dispatch(saveNews({ cid, results, pre_timestamp }));
      });
  };

  // 7. 调用无限列表加载组件 获取新闻列表
  // 8. 渲染新闻列表

  // 当页面离开时记录当前频道对应的新闻列表的滚动位置
  useEffect(() => {
    // 重新设置滚动位置
    setContainerScrollTop(distance | 0);
    return () => {
      // 组件卸载之前执行
      dispatch(saveDistance({ cid, distance: getScrollTop() }));
    };
  }, [getScrollTop, cid, dispatch, setContainerScrollTop, distance]);

  return (
    <>
      <ul className={styles.news}>
        {channelNews?.results.map((news) => (
          <NewsItem key={news.art_id} news={news} />
        ))}
      </ul>
      {/* 当我们请求到最后一页数据的时候, 服务端返回的 pre_timestamp 将会是 null, 也就是说, 当时间戳不为 null 的时候, 就是有下一页数据的 */}
      <Infinite
        hasMore={channelNews?.pre_timestamp !== null}
        loadMore={loadMore}
      />
    </>
  );
}
